gh-154199: Fix find_msvcrt() on builds with a truncated sys.version#154209
Open
SynaptSea wants to merge 1 commit into
Open
gh-154199: Fix find_msvcrt() on builds with a truncated sys.version#154209SynaptSea wants to merge 1 commit into
SynaptSea wants to merge 1 commit into
Conversation
…sion
Python/getversion.c formats the compiler identification with \\%.80s\\, so the
long banner emitted by clang-cl builds is cut off before the \\MSC v.\\ marker
that _get_build_version() looks for. It then fell back to \\
eturn 6\\, i.e.
'assume MSVC 6', and find_msvcrt() handed out msvcrt.dll -- a CRT that does not
share its errno with the ucrt that _ctypes is linked against, so
ctypes.get_errno() silently returned stale values.
Report the build version as unknown instead, so find_msvcrt() and
find_library('c') return None exactly as they do on modern MSVC builds.
Also handle a second truncation case found while fixing this one: when the cut
lands inside the version number itself the marker is present but the digits are
not, and the unpacking assignment raised ValueError out of find_library('c').
Copilot stopped reviewing on behalf of
SynaptSea due to an error
July 20, 2026 01:16
chris-eibl
self-requested a review
July 20, 2026 10:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #154199
Python/getversion.cformats the compiler identification with"%.80s". The bannerthat
PC/pyconfig.hemits for clang-cl builds is"[Clang " __clang_version__ "] 64 bit (AMD64) with MSC v.<n> CRT]", and official LLVMWindows binaries have an 86-character
__clang_version__(version + repo URL + fullcommit hash), so the tail carrying the
"MSC v."marker is always cut off.ctypes.util._get_build_version()looks for that marker and, not finding it, fell backto
return 6— "assume the compiler is MSVC 6".find_msvcrt()then maps version 6 tomsvcrt.dllandfind_library('c')returns it. That CRT does not share itserrnowiththe ucrt that
_ctypesis linked against, soctypes.get_errno()silently returns stalevalues after a failing call. No exception is raised — the caller just gets wrong data.
This reports the build version as unknown instead, so
find_msvcrt()andfind_library('c')returnNoneexactly as they already do on modern MSVC builds(where
_get_build_version()returns 14.x and the "CRT is no longer directly loadable"branch from bpo-23606 applies).
find_msvcrt()already had aversion is Noneguard, sothis simply routes truncated banners into the existing safe path.
While fixing that I found a second manifestation of the same truncation: when the cut
lands inside the version digits, the marker is present but the number is not, and
s, rest = sys.version[i:].split(" ", 1)raisesValueError: not enough values to unpackout offind_library('c')— worse than a wrongreturn value.
partition()handles both cases. Happy to split that into its own PR ifyou would rather keep this one to the single change.
The documented contract is unchanged:
Doc/library/ctypes.rstalready saysfind_msvcrt()returns
None"if the name of the library cannot be determined", and thatfind_library("c")fails on Windows. Only the undocumented MSVC-6 fallback is removed.
Testing
Added
FindLibraryWindowstoLib/test/test_ctypes/test_find.py. It patchessys.versionwith
unittest.mock, so it exercises the fix on any Windows build — a clang-cl build is notneeded to run it. It covers a truncated clang banner, a truncation inside the marker, and a
real MSVC banner (asserting 14.4 /
None, so the MSVC path is pinned against regression).On a local clang-cl free-threaded build,
python -m test test_ctypes:run=674 failures=1(test_errno.Test.test_open:AssertionError: 0 != 2) — FAILURErun=678 skipped=40— SUCCESStest_opennow skips with'Unable to find C library', identical to an MSVC build. Threetests move from run to skipped (
test_errno.test_open,test_loading.test_find,test_callbacks.test_issue_8959_a); all three already skip on MSVC builds, so this convergesclang-cl onto the reference platform rather than reducing coverage. Verified no MSVC
regression by mocking real banners:
MSC v.1944-> 14.4,MSC v.1600->msvcr100.dll,MSC v.1200->msvcrt.dll(a genuine MSVC 6 build is unaffected).The root cause is arguably the
"%.80s"precision inPython/getversion.c—sys.versionalso ends mid-hash without its closing bracket on these builds, and it broke
sysconfig.get_platform()the same way in gh-145410. I have not touched it here since thatwould change
sys.versioncontent for every consumer, but it may be worth a separate issue.